﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Hosting;
using System.Xml.Serialization;

namespace WebDotNet.Samples.WdnMicroBlog.App
{
	/// <summary>
	/// Simple xml repository class.
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class XmlRepository<T>
	{
		private List<T> _cache = null;
		private readonly string _path;

		public XmlRepository()
			: this("~/App_Data/{0}.xml")
		{
		}

		public XmlRepository(string path)
		{
			_path = path;
		}

		public List<T> List()
		{
			if (_cache == null)
			{
				_cache = load();
			}

			return _cache;
		}

		public XmlRepository<T> Save()
		{
			save(_cache);
			_cache = null;

			return this;
		}

		public XmlRepository<T> RemoveAll()
		{
			this.List().RemoveAll(t => true);

			return this;
		}

		public XmlRepository<T> RemoveAll(Predicate<T> predicate)
		{
			this.List().RemoveAll(predicate);

			return this;
		}

		public XmlRepository<T> Add(T entity)
		{
			this.List().Add(entity);

			return this;
		}

		public XmlRepository<T> Update(T entity)
		{
			this.List().Remove(entity);
			this.Add(entity);

			return this;
		}

		private List<T> load()
		{
			string fileName = getFileName<T>();

			if (File.Exists(fileName))
			{
				return toObject<List<T>>(fileName);
			}
			else
			{
				return new List<T>();
			}
		}

		private void save(List<T> entities)
		{
			string fileName = getFileName<T>();

			toFile(entities, fileName);
		}

		private void toFile<T>(T entity, string fileName)
		{
			XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
			using (TextWriter textWriter = new StreamWriter(fileName))
			{
				xmlSerializer.Serialize(textWriter, entity);
			}
		}

		private static T toObject<T>(string fileName)
		{
			XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
			using (TextReader textReader = new StreamReader(fileName))
			{
				T entity = (T)xmlSerializer.Deserialize(textReader);
				return entity;
			}
		}

		private string getFileName<T>()
		{
			string fileName = string.Format(this._path, typeof(T).FullName);

			if (fileName.StartsWith("~"))
			{
				fileName = HostingEnvironment.MapPath(fileName);
			}

			return fileName;
		}
	}
}
